"""
下单管理模块
处理闲鱼下单流程：获取收货地址 -> 渲染订单 -> 创建订单
"""

import asyncio
from loguru import logger
from core.command_manager import CommandRes
from modules.goofish_api import GoofishAPIClient, ResponseCode
from modules.order_queue import OrderQueue


class OrderManager:
    def __init__(self, state: 'StateManager', browser_manager=None, search_manager=None):
        """
        Args:
            state: 状态管理器
            browser_manager: 浏览器管理器（可选）
            search_manager: 搜索管理器（可选，用于过滤PC无法下单的商品）
        """
        self.state = state
        self.browser_manager = browser_manager
        self.search_manager = search_manager  # ✅ 用于访问过滤列表
        
        # ✅ 调试：检查search_manager是否正确传入
        if not self.search_manager:
            logger.debug(f"⚠️  OrderManager初始化时search_manager未传入（这是正常的，如果是从其他地方创建实例）")
        else:
            logger.debug(f"✅ OrderManager初始化时search_manager已设置: {type(self.search_manager).__name__}")
        
        # 使用API客户端
        self.api_client = GoofishAPIClient(state, browser_manager)
        
        # 缓存收货地址
        self._address_list = None
        self._default_address = None
        
        # ✅ 订单队列（串行处理，防止并发冲突）
        self.order_queue = OrderQueue(delay_between_orders=2.0)
        self.order_queue.set_order_processor(self)
        logger.info("✅ 订单队列已初始化，订单间延迟=2秒")
    
    async def get_address_list(self, use_cache: bool = True) -> dict:
        """
        获取收货地址列表
        Args:
            use_cache: 是否使用缓存
        Returns:
            API响应
        """
        if use_cache and self._address_list:
            logger.info("使用缓存的收货地址列表")
            return self._address_list
        
        try:
            logger.info("获取收货地址列表...")
            result = await self.api_client.get_address_list()
            
            # ✅ 统一错误处理：goofish_api 已处理所有错误码
            ret_codes = result.get("ret", [])
            if not ret_codes:
                logger.error(f"❌ API响应格式错误，完整返回: {result}")
                return {"success": False, "msg": "API响应格式错误"}
            
            code = ret_codes[0]
            
            # 成功：返回SUCCESS或SUCCESS开头的码
            if code == ResponseCode.SUCCESS or (isinstance(code, str) and code.startswith("SUCCESS")):
                outer_data = result.get("data", {})
                inner_data = outer_data.get("data", {})
                addresses = inner_data.get("addressList", [])
                
                # ✅ 临时屏蔽函数
                def mask_name(name: str) -> str:
                    """屏蔽姓名：首尾保留，中间用*替换"""
                    if not name or len(name) <= 1:
                        return name
                    if len(name) == 2:
                        return name[0] + "*"
                    # 长度>=3：首字符 + 中间用8替换 + 尾字符
                    return name[0] + "*" * (len(name) - 2) + name[-1]
                
                def mask_address(address: str) -> str:
                    """屏蔽地址：首尾保留3个文字，中间用*替换"""
                    if not address:
                        return address
                    if len(address) <= 6:
                        # 如果地址长度<=6，全部用*替换
                        return "*" * len(address)
                    # 长度>6：前3个字符 + 中间用*替换 + 后3个字符
                    return address[:3] + "*" * (len(address) - 6) + address[-3:]
                
                def mask_phone(phone: str) -> str:
                    """屏蔽电话号码：保留首尾3个数字，中间用*替换"""
                    if not phone:
                        return phone
                    phone_str = str(phone).strip()
                    if len(phone_str) <= 6:
                        # 如果电话号码长度<=6，全部用*替换
                        return "*" * len(phone_str)
                    # 长度>6：前3个数字 + 中间用*替换 + 后3个数字
                    return phone_str[:3] + "*" * (len(phone_str) - 6) + phone_str[-3:]
                
                # 解析并格式化地址列表
                formatted_addresses = []
                for addr in addresses:
                    original_name = addr.get("fullName", "")
                    original_phone = addr.get("mobile", "")
                    original_full_address = addr.get("formatFullAddress", "")
                    original_address_detail = addr.get("addressDetail", "")
                    
                    formatted_addr = {
                        "id": str(addr.get("addressId")),
                        "name": mask_name(original_name),  # ✅ 屏蔽姓名
                        "phone": mask_phone(original_phone),  # ✅ 屏蔽电话号码
                        "province": addr.get("province"),
                        "city": addr.get("city"),
                        "area": addr.get("area"),
                        "town": addr.get("town", ""),
                        "addressDetail": mask_address(original_address_detail),  # ✅ 屏蔽详细地址
                        "fullAddress": mask_address(original_full_address),  # ✅ 屏蔽完整地址
                        "isDefault": addr.get("status") == 1,  # status=1表示默认地址
                        "_raw": addr,
                        # ✅ 保留原始数据（用于实际下单时使用）
                        "_original": {
                            "name": original_name,
                            "phone": original_phone,
                            "fullAddress": original_full_address,
                            "addressDetail": original_address_detail
                        }
                    }
                    formatted_addresses.append(formatted_addr)
                    
                    # 记录默认地址
                    if formatted_addr["isDefault"]:
                        self._default_address = formatted_addr
                
                # 缓存格式化后的地址列表
                self._address_list = {
                    "success": True,
                    "addresses": formatted_addresses
                }
                
                logger.success(f"✅ 获取收货地址成功，共{len(formatted_addresses)}个地址")
                return {"success": True, "addresses": formatted_addresses}
            
            # ❌ 失败：goofish_api已统一处理，直接返回错误信息（包含error_type）
            error_msg = result.get("msg", f"获取地址失败: {code}")
            error_type = result.get("error_type", "api_error")
            logger.error(f"获取收货地址失败: {error_msg} (type={error_type})")
            
            # 如果是登录过期，goofish_api已统一处理（刷新登录+发送状态更新）
            # 这里只需要记录日志即可
            if error_type == "session_expired":
                logger.warning("⚠️ 检测到登录过期（goofish_api已处理刷新和状态通知）")
            
            return {
                "success": False,
                "msg": error_msg,
                "code": code,
                "error_type": error_type,
                "raw_response": result.get("raw_risk_response")  # 如果是风控错误，包含完整响应
            }
                
        except Exception as e:
            logger.exception(f"获取收货地址异常: {e}")
            return {"success": False, "msg": str(e), "error_type": "exception"}
    
    async def get_default_address(self) -> dict:
        """
        获取默认收货地址
        Returns:
            默认地址信息
        """
        if not self._address_list:
            await self.get_address_list()
        
        if self._default_address:
            return {"success": True, "address": self._default_address}
        else:
            return {"success": False, "msg": "未找到默认地址"}
    
    async def get_item_detail(self, item_id: str) -> dict:
        """
        获取商品详情
        Args:
            item_id: 商品ID
        Returns:
            商品详情
        """
        try:
            logger.info(f"获取商品详情: {item_id}")
            result = await self.api_client.get_item_detail(item_id)
            
            ret_codes = result.get("ret", [])
            if not ret_codes:
                return {"success": False, "msg": "API响应格式错误"}
            
            code = ret_codes[0]
            
            if code == ResponseCode.SUCCESS or code.startswith("SUCCESS"):
                data = result.get("data", {})
                logger.success(f"获取商品详情成功")
                return {"success": True, "data": data}
            else:
                error_msg = result.get("msg", "获取商品详情失败")
                logger.error(f"获取商品详情失败: {code} - {error_msg}")
                return {"success": False, "msg": error_msg, "code": code}
                
        except Exception as e:
            logger.exception(f"获取商品详情异常: {e}")
            return {"success": False, "msg": str(e)}
    
    async def render_order(self, item_id: str) -> dict:
        """
        渲染订单（获取订单预览信息）
        Args:
            item_id: 商品ID
        Returns:
            订单渲染结果
        """
        try:
            # ✅ 精简日志：渲染订单不记录INFO级别日志
            # ✅ 直接渲染订单，不预检查商品详情（争取抢单时机）
            # 如果不支持PC下单，API会返回FAIL_BIZ_PC_CAN_NOT_TRADE错误码，再处理即可
            result = await self.api_client.render_order(item_id)
            
            ret_codes = result.get("ret", [])
            if not ret_codes:
                return {"success": False, "msg": "API响应格式错误"}
            
            code = ret_codes[0]
            
            if code == ResponseCode.SUCCESS or code.startswith("SUCCESS"):
                data = result.get("data", {})
                # ✅ 精简日志：订单渲染成功不记录日志
                return {"success": True, "data": data}
            else:
                error_msg = result.get("msg", "订单渲染失败")
                logger.error(f"订单渲染失败: {code} - {error_msg}")
                # ✅ render_order不会返回FAIL_BIZ_PC_CAN_NOT_TRADE，该错误在create_order时才返回
                return {"success": False, "msg": error_msg, "code": code}
                
        except Exception as e:
            logger.exception(f"订单渲染异常: {e}")
            return {"success": False, "msg": str(e)}
    
    async def create_order(
        self,
        item_id: str,
        address_id: str = None,
        seller_id: str = None,
        **kwargs
    ) -> dict:
        """
        创建订单（按照C#逻辑修复）
        Args:
            item_id: 商品ID
            address_id: 收货地址ID（可选，默认使用默认地址）
            seller_id: 卖家ID（可选，从render_order获取）
            **kwargs: 其他订单参数
        Returns:
            订单创建结果
        
        流程（按照C# CreateOrderForAccount逻辑）：
        1. 调用 render_order 获取 itemBuyInfo 数组
        2. 遍历 itemBuyInfo，设置每个的 deliverId（地址ID）
        3. 调用 create_order，传入整个 itemBuyInfo 数组（序列化为JSON）
        """
        try:
            # ✅ 步骤1：调用 render_order 获取订单信息
            render_result = await self.render_order(item_id)
            if not render_result.get("success"):
                return {"success": False, "msg": f"渲染订单失败: {render_result.get('msg', '未知错误')}"}
            
            render_data = render_result.get("data", {})
            # ✅ 获取 commonData.itemBuyInfo 数组（按照C#逻辑）
            common_data = render_data.get("commonData", {})
            item_buy_info_list = common_data.get("itemBuyInfo", [])
            
            if not item_buy_info_list or len(item_buy_info_list) == 0:
                return {"success": False, "msg": "渲染订单返回的itemBuyInfo为空"}
            
            # ✅ 如果没有指定地址，使用默认地址
            if not address_id:
                default_addr = await self.get_default_address()
                if not default_addr.get("success"):
                    return {"success": False, "msg": "未找到默认收货地址"}
                # ✅ 使用id字段（格式化后的地址使用id，原始数据在_raw中）
                address_id = default_addr["address"].get("id") or default_addr["address"].get("addressId")
            
            # ✅ 步骤2：遍历 itemBuyInfo，设置每个的 deliverId（按照C#逻辑）
            # ⚠️ 重要：确保 urlParams 字段保持为字符串（如果被解析为字典，需要重新序列化）
            import json
            for item_buy_info in item_buy_info_list:
                item_buy_info["deliverId"] = address_id
                # ✅ 确保 urlParams 字段是字符串（C#代码中它应该是JSON字符串）
                if "urlParams" in item_buy_info:
                    url_params = item_buy_info["urlParams"]
                    # 如果是字典/对象，需要序列化为字符串
                    if isinstance(url_params, (dict, list)):
                        item_buy_info["urlParams"] = json.dumps(url_params, ensure_ascii=False, separators=(',', ':'))
                    # 如果已经是字符串，保持不变
                    elif not isinstance(url_params, str):
                        # 其他类型也转为字符串
                        item_buy_info["urlParams"] = str(url_params)
            
            # ✅ 精简日志：创建订单不记录INFO级别日志（除非失败）
            
            # ✅ 步骤3：调用 create_order，传入整个 itemBuyInfo 数组（按照C#逻辑）
            result = await self.api_client.create_order(
                item_buy_info_list=item_buy_info_list,
                **kwargs
            )
            
            # ✅ 统一错误处理：goofish_api 已处理所有错误码
            ret_codes = result.get("ret", [])
            if not ret_codes:
                return {"success": False, "msg": "API响应格式错误"}
            
            code = ret_codes[0]
            
            if code == ResponseCode.SUCCESS or (isinstance(code, str) and code.startswith("SUCCESS")):
                data = result.get("data", {})
                order_id = data.get("orderId") or data.get("bizOrderId")
                logger.success(f"订单创建成功! 订单号: {order_id}")
                return {
                    "success": True,
                    "msg": "订单创建成功",
                    "data": data,
                    "order_id": order_id
                }
            else:
                # ❌ 失败：goofish_api已统一处理，直接返回错误信息
                error_msg = result.get("msg", f"订单创建失败: {code}")
                error_type = result.get("error_type", "api_error")
                logger.error(f"订单创建失败: {error_msg} (type={error_type})")
                
                # ✅ 提取核心错误信息（避免嵌套）
                # 如果错误信息包含"::"，尝试解析JSON格式的描述
                code_str = str(code)
                if "FAIL_BIZ_ITEM_CANNOT_BUY_ERROR" in code_str:
                    # ✅ 商品已下架，使用友好提示
                    error_msg = "商品已下架，无法购买"
                    # ✅ 提取toastMsg作为友好提示（如果需要更详细的错误信息）
                    try:
                        error_data = result.get("data", {})
                        if isinstance(error_data, dict):
                            toast_msg = error_data.get("toastMsg") or error_data.get("msg")
                            if toast_msg:
                                error_msg = toast_msg
                            else:
                                # 尝试从error_msg中提取
                                if "::" in error_msg:
                                    parts = error_msg.split("::")
                                    if len(parts) > 1:
                                        try:
                                            import json
                                            desc_json = json.loads(parts[-1])
                                            if "toastMsg" in desc_json:
                                                error_msg = desc_json["toastMsg"]
                                        except:
                                            error_msg = "当前商品无法购买"
                    except:
                        error_msg = "当前商品无法购买"
                elif "FAIL_BIZ_DEFAULT_INVENTORY_NOT_ENOUGH" in code_str:
                    # ✅ 提取toastMsg作为友好提示（商品已抢光）
                    try:
                        error_data = result.get("data", {})
                        if isinstance(error_data, dict):
                            toast_msg = error_data.get("toastMsg") or error_data.get("msg")
                            if toast_msg:
                                error_msg = toast_msg
                            else:
                                # 尝试从error_msg中提取
                                if "::" in error_msg:
                                    parts = error_msg.split("::")
                                    if len(parts) > 1:
                                        try:
                                            import json
                                            desc_json = json.loads(parts[-1])
                                            if "toastMsg" in desc_json:
                                                error_msg = desc_json["toastMsg"]
                                        except:
                                            error_msg = "商品已抢光"
                    except:
                        error_msg = "商品已抢光"
                
                # ✅ 如果返回PC无法下单的错误码，将该商品加入过滤列表
                # 注意：FAIL_BIZ_PC_CAN_NOT_TRADE 是在 create_order 时返回的，render_order 不会返回此错误
                if ResponseCode.FAIL_BIZ_PC_CAN_NOT_TRADE in code_str or "FAIL_BIZ_PC_CAN_NOT_TRADE" in code_str:
                    if self.search_manager:
                        self.search_manager.add_mobile_only_item(item_id)
                        logger.info(f"✅ 订单创建时检测到PC无法下单，商品 {item_id} 已加入过滤列表（后续搜索将自动过滤）")
                    else:
                        # ✅ 尝试从main模块获取SEARCH实例（备用方案）
                        logger.warning(f"⚠️  无法添加商品 {item_id} 到过滤列表（search_manager未设置），尝试备用方案...")
                        try:
                            import sys
                            # 尝试获取main模块中的SEARCH实例
                            main_module = sys.modules.get('__main__')
                            if main_module:
                                # 检查是否有SEARCH属性
                                if hasattr(main_module, 'SEARCH'):
                                    search_manager = getattr(main_module, 'SEARCH')
                                    if search_manager and hasattr(search_manager, 'add_mobile_only_item'):
                                        search_manager.add_mobile_only_item(item_id)
                                        logger.info(f"✅ 通过备用方案已添加商品 {item_id} 到过滤列表（后续搜索将自动过滤）")
                                    else:
                                        logger.warning(f"⚠️  备用方案：main模块中的SEARCH对象无效")
                                else:
                                    logger.warning(f"⚠️  备用方案：main模块中未找到SEARCH")
                            else:
                                logger.warning(f"⚠️  备用方案：无法获取main模块")
                        except Exception as e:
                            logger.warning(f"⚠️  备用方案失败: {e}")
                
                return {
                    "success": False,
                    "msg": error_msg,
                    "code": code,
                    "error_type": error_type,
                    "raw_response": result.get("raw_risk_response")
                }
                
        except Exception as e:
            logger.exception(f"订单创建异常: {e}")
            return {"success": False, "msg": str(e)}
    
    async def handle_get_address(self, msg):
        """
        处理来自TCP的get_address命令
        Args:
            msg: 命令消息
        Returns:
            命令响应 - 返回地址列表
        """
        # ✅ 注意：封禁检查已在 goofish_api.request 中统一处理，这里不再重复检查
        # 检查是否已登录
        if self.state.get("login_status") != "logged_in":
            return CommandRes.GetAddress().Fail(msg="未登录，请先登录")
        
        try:
            logger.info("📡 处理get_address命令...")
            
            # ✅ 获取force_test参数（已移除，封禁只阻止搜索和下单，不阻止获取地址）
            # 获取地址列表（不使用缓存，确保数据最新）
            result = await self.get_address_list(use_cache=False)
            logger.info(f"📝 get_address_list返回: success={result.get('success')}, addresses count={len(result.get('addresses', []))}")
            
            if result.get("success"):
                addresses = result.get("addresses", [])
                logger.success(f"✅ 获取收货地址成功，共{len(addresses)}个地址")
                
                # 打印第一个地址的结构（如果有）
                # if addresses:
                #     logger.info(f"📝 第一个地址的keys: {list(addresses[0].keys())}")
                
                # ✅ get_address_list已经格式化成前端需要的格式，直接返回即可
                response = CommandRes.GetAddress().Success(
                    msg=f"获取地址成功，共{len(addresses)}个",
                    data={
                        "addresses": addresses,
                        "count": len(addresses)
                    }
                )
                # logger.info(f"📝 最终返回给前端的响应: {response}")
                return response
            else:
                error_msg = result.get("msg", "获取地址失败")
                logger.error(f"获取地址失败: {error_msg}")
                return CommandRes.GetAddress().Fail(
                    msg=f"获取地址失败: {error_msg}"
                )
                
        except Exception as e:
            logger.exception(f"获取地址异常: {e}")
            return CommandRes.GetAddress().Fail(msg=f"获取地址异常: {e}")
    
    def set_tcp_client(self, tcp_client):
        """设置TCP客户端（用于队列发送结果）"""
        self.order_queue.set_tcp_client(tcp_client)
    
    async def handle_order(self, msg):
        """
        处理来自TCP的order命令（队列入口）
        Args:
            msg: 命令消息
        Returns:
            命令响应（立即返回，不等待执行完成）
        """
        if not msg or not msg.data:
            return CommandRes.Order().Fail(msg="缺少订单参数")
        
        # ✅ 添加到队列（立即返回）
        order_cmd = msg.to_dict()
        result = await self.order_queue.add_order(order_cmd)
        
        # 立即返回响应（不等待执行完成）
        return CommandRes.Order().Success(
            msg=result.get("msg", "订单已加入队列"),
            data=result.get("data", {})
        )
    
    async def handle_order_direct(self, msg):
        """
        直接处理订单（不经过队列，由队列处理器调用）
        Args:
            msg: 命令消息
        Returns:
            命令响应
        """
        if not msg or not msg.data:
            return CommandRes.Order().Fail(msg="缺少订单参数")
        
        item_id = msg.data.get("item_id") or msg.data.get("itemId")
        item_url = msg.data.get("item_url") or msg.data.get("itemUrl")
        address_id = msg.data.get("address_id") or msg.data.get("addressId")
        
        if not item_id:
            # 尝试从URL中提取item_id
            if item_url and "itemId=" in item_url:
                item_id = item_url.split("itemId=")[1].split("&")[0]
            else:
                return CommandRes.Order().Fail(msg="缺少商品ID")
        
        # ✅ 注意：封禁检查已在 goofish_api.request 中统一处理，这里不再重复检查
        # 检查是否可以下单
        ready, reason = self.state.is_ready_for_order()
        if not ready:
            # ✅ 优化：如果reason已经包含完整错误信息，直接返回（避免嵌套）
            # 如果reason是简短的提示（如"浏览器未运行"），则添加"无法下单:"前缀
            if len(reason) > 20 or ":" in reason or "FAIL_BIZ" in reason or "FAIL_SYS" in reason:
                # reason已经包含完整错误信息，直接返回
                return CommandRes.Order().Fail(msg=reason)
            else:
                # reason是简短提示，添加前缀
                return CommandRes.Order().Fail(msg=f"无法下单: {reason}")
        
        try:
            # 设置下单状态
            self.state.start_ordering()
            # ✅ 精简日志：开始下单不记录INFO级别日志（除非失败）
            
            # 创建订单
            result = await self.create_order(
                item_id=item_id,
                address_id=address_id
            )
            
            if result.get("success"):
                self.state.stop_ordering()
                return CommandRes.Order().Success(
                    msg="订单创建成功",
                    data={
                        "item_id": item_id,
                        "order_id": result.get("order_id"),
                        "order_data": result.get("data")
                    }
                )
            else:
                # ❌ 失败：goofish_api已统一处理，直接返回错误信息
                error_msg = result.get("msg", "下单失败")
                error_type = result.get("error_type", "api_error")
                error_code = 1  # 默认错误码
                api_code = result.get("code", "")
                
                # 根据错误类型设置错误码
                if error_type == "session_expired":
                    error_code = 2  # 登录过期
                elif error_type == "token_error":
                    error_code = 3  # Token错误
                elif error_type == "risk_control":
                    error_code = 4  # 风控
                
                # ✅ 优化：区分封禁错误和业务错误
                # 只有封禁错误才设置work_status=error，业务错误只记录警告日志并发送到前端
                code_str = str(api_code)
                is_pc_cannot_trade = ResponseCode.FAIL_BIZ_PC_CAN_NOT_TRADE in code_str or "FAIL_BIZ_PC_CAN_NOT_TRADE" in code_str
                is_inventory_holding = ResponseCode.FAIL_BIZ_ALL_INVENTORY_WITH_HOLDING in code_str or "FAIL_BIZ_ALL_INVENTORY_WITH_HOLDING" in code_str
                is_item_cannot_buy = ResponseCode.FAIL_BIZ_ITEM_CANNOT_BUY_ERROR in code_str or "FAIL_BIZ_ITEM_CANNOT_BUY_ERROR" in code_str
                is_inventory_not_enough = ResponseCode.FAIL_BIZ_DEFAULT_INVENTORY_NOT_ENOUGH in code_str or "FAIL_BIZ_DEFAULT_INVENTORY_NOT_ENOUGH" in code_str
                is_banned = error_type == "account_banned" or result.get("banned", False)
                # ✅ 检查 error_type 是否为 business_error（goofish_api 已标记）
                is_business_error = error_type == "business_error" or result.get("is_business_error", False) or is_pc_cannot_trade or is_inventory_holding or is_item_cannot_buy or is_inventory_not_enough
                
                # 发送错误日志到前端实时日志和notification
                if self.browser_manager and self.browser_manager.tcp_client:
                    try:
                        # ✅ 获取账号信息用于日志显示
                        account = self.state.get("account") or ""
                        account_nickname = self.state.get("account_nickname") or ""
                        client_name = getattr(self.browser_manager, 'client_name', '') or ""
                        remark = ""  # 备注信息需要从控制端获取
                        
                        # ✅ 构建账号显示信息（优先使用昵称，其次账号名，最后客户端名）
                        account_display = account_nickname or account or client_name or ""
                        
                        warning_log_msg = {
                            "event": "order_error",
                            "direction": "res",
                            "success": False,
                            "code": error_code,
                            "msg": error_msg,
                            "data": {
                                "item_id": item_id,
                                "error_type": error_type,
                                "api_code": api_code,
                                "is_business_error": is_business_error,
                                "is_banned": is_banned,
                                "account": account_display,  # ✅ 添加账号信息
                                "client_id": self.state.get("client_id", "")
                            }
                        }
                        asyncio.create_task(self.browser_manager.tcp_client.send(warning_log_msg))
                        logger.info(f"✅ 已发送订单错误日志到前端实时日志: {error_msg}")
                    except Exception as e:
                        logger.warning(f"发送错误日志失败: {e}")
                
                if is_banned:
                    # 封禁错误：保持封禁状态，不要设置work_status为error
                    # ✅ 如果work_status不是banned，设置为banned以便前端显示
                    if self.state.get("work_status") != "banned":
                        self.state.mark_banned()
                        self.state.set_work_status("banned")  # 设置工作状态为"banned"（封禁中）
                    # ✅ 只设置last_error，不要调用set_error（set_error会把work_status设置为error）
                    self.state.set("last_error", f"下单失败: {error_msg}")
                    logger.error(f"❌ 账号被封禁，无法下单: {error_msg}")
                elif error_type in ["session_expired", "token_error", "risk_control", "risk_control_cooldown", "risk_control_high_frequency", "risk_api_failure", "retry_error", "retry_timeout"]:
                    # ⚠️ 这些错误由goofish_api已尝试自动恢复但失败，与搜索逻辑一致：重置状态允许继续
                    # - session_expired: 已尝试删除token重试、浏览器刷新
                    # - token_error: 已尝试自动刷新token
                    # - risk_control: 已尝试过风控验证（调用risk.py获取x5sec）
                    # - risk_control_cooldown: 账号冷却中（goofish_api已设置冷却期）
                    # - risk_control_high_frequency: 连续3次通过风控后仍触发（goofish_api已设置20分钟冷却）
                    # - risk_api_failure: 连续3次风控接口失败（第三方接口问题）
                    # - retry_error/retry_timeout: 重试请求失败
                    # 如果到这里说明自动恢复失败，重置状态让队列继续处理下一个订单
                    self.state.stop_ordering()  # 重置 work_status 为 idle
                    logger.warning(f"⚠️  {error_type}: {error_msg}，已重置状态，等待下次任务")
                    # 不调用set_error，避免停止队列（与搜索逻辑完全一致）
                elif is_business_error:
                    # ✅ 业务性错误：只重置状态，不设置错误状态（工作状态保持正常）
                    # ✅ 业务错误不应该影响账号状态，但保留last_error以便在详情面板中显示
                    self.state.stop_ordering()
                    # ✅ 清除之前的错误状态（如果有），但不清除last_error（保留业务错误信息）
                    if self.state.get("work_status") == "error":
                        self.state.set_work_status("idle")
                    # ✅ 保留last_error，但标记为业务错误（不影响工作状态显示）
                    # 注意：不清除last_error，以便在详情面板的"最后错误"字段中显示
                    
                    if is_pc_cannot_trade:
                        logger.warning(f"⚠️  PC无法下单（商品 {item_id} 已加入过滤列表），继续尝试其他商品")
                    elif is_item_cannot_buy:
                        logger.warning(f"⚠️  商品 {item_id} 无法购买（{error_msg}），跳过继续尝试其他商品")
                    elif is_inventory_holding:
                        logger.warning(f"⚠️  商品 {item_id} 库存被锁定（有人拍下但未付款），跳过继续尝试其他商品")
                    elif is_inventory_not_enough:
                        logger.warning(f"⚠️  商品 {item_id} 已抢光（{error_msg}），跳过继续尝试其他商品")
                    else:
                        logger.warning(f"⚠️  业务错误（商品 {item_id}）: {error_msg}，跳过继续尝试其他商品")
                else:
                    # 其他系统错误（如API异常、登录过期等）：设置错误状态
                    # 注意：这些错误可能阻止后续操作，需要人工处理
                    self.state.set_error(f"下单失败: {error_msg}")
                    logger.error(f"❌ 下单失败: {error_msg}")
                
                return CommandRes.Order().Fail(
                    msg=error_msg,
                    code=error_code,
                    data={
                        "error_type": error_type,
                        "api_code": api_code,
                        "raw_response": result.get("raw_response")
                    }
                )
                
        except Exception as e:
            logger.exception(f"下单异常: {e}")
            self.state.set_error(str(e))
            return CommandRes.Order().Fail(msg=f"下单异常: {e}")
        finally:
            # 确保恢复状态
            if self.state.get("work_status") == "ordering":
                self.state.stop_ordering()

    async def handle_cancel_order(self, msg):
        """处理取消订单命令"""
        if not msg or not msg.data:
            logger.warning("❌ 取消订单命令缺少参数")
            return CommandRes.OrderCancel().Fail(msg="缺少参数")
        
        # ✅ 注意：封禁检查已在 goofish_api.request 中统一处理，这里不再重复检查
        order_id = msg.data.get("order_id") or msg.data.get("orderId")
        reason = msg.data.get("reason") or "不想买了"
        
        if not order_id:
            logger.warning("❌ 取消订单命令缺少订单ID")
            return CommandRes.OrderCancel().Fail(msg="缺少订单ID")
        
        try:
            logger.info(f"📥 收到取消订单命令: order_id={order_id}, reason={reason}")
            result = await self.api_client.cancel_order(order_id, reason)
            ret_codes = result.get("ret", [])
            
            if ret_codes and (ret_codes[0] == ResponseCode.SUCCESS or str(ret_codes[0]).startswith("SUCCESS")):
                logger.success(f"✅ 订单取消成功: order_id={order_id}")
                return CommandRes.OrderCancel().Success(msg="取消成功", data={"order_id": order_id})
            else:
                logger.error(f"❌ 订单取消失败: {result.get('msg', '取消失败')}")
                return CommandRes.OrderCancel().Fail(msg=result.get("msg", "取消失败"), data={"code": ret_codes[0] if ret_codes else ''})
        except Exception as e:
            logger.exception(e)
            return CommandRes.OrderCancel().Fail(msg=str(e))

